using System;
using System.Collections.Generic;
using Xunit;
using WenYu.Core.Lexer;
using WenYu.Core.Parser;

namespace WenYu.Tests.DocumentValidation;

/// <summary>
/// 文档05-函数.md的示例验证测试
/// </summary>
public class Doc05FunctionsValidation
{
    private List<Token> Tokenize(string source)
    {
        var lexer = new WenYuLexer(source);
        return lexer.Tokenize();
    }

    private Program Parse(string source)
    {
        var lexer = new WenYuLexer(source);
        var tokens = lexer.Tokenize();
        var parser = new WenYuParser(tokens);
        return parser.Parse();
    }

    #region 无参数无返回值函数测试

    [Fact]
    public void Example1_VoidNoParams()
    {
        var source = @"求 法 打印欢迎{
    输出（""=============""）。
    输出（"" 欢迎使用文语！""）。
    输出（""=============""）。
    回。
}

打印欢迎（）。";

        var tokens = Tokenize(source);
        Assert.NotEmpty(tokens);

        var tokenValues = new List<string>();
        foreach (var token in tokens)
        {
            if (!string.IsNullOrWhiteSpace(token.Value))
                tokenValues.Add(token.Value);
        }

        Assert.Contains("求", tokenValues);
        Assert.Contains("法", tokenValues);
        Assert.Contains("回", tokenValues);

        var ast = Parse(source);
        Assert.NotNull(ast);
    }

    #endregion

    #region 有参数无返回值函数测试

    [Fact]
    public void Example2_ParamsNoReturn()
    {
        var source = @"文字 名字 求 法 问候{
    输出（""你好，"" + 名字 + ""！""）。
    输出（""欢迎来到文语的世界！""）。
    回。
}

问候（""小明""）。
问候（""小红""）。";

        var tokens = Tokenize(source);
        Assert.NotEmpty(tokens);
        var ast = Parse(source);
        Assert.NotNull(ast);
    }

    [Fact]
    public void Example3_ParamsWithValidation()
    {
        var source = @"整型 年龄 求 法 检查年龄{
    若 年龄 《 0 则{
        输出（""错误：年龄不能为负数""）。
        回。
    }
    若 年龄 》 150 则{
        输出（""错误：年龄超过合理范围""）。
        回。
    }
    输出（""年龄有效："" + 年龄的文字）。
    回。
}

检查年龄（-5）。
检查年龄（25）。
检查年龄（200）。";

        var tokens = Tokenize(source);
        Assert.NotEmpty(tokens);
        var ast = Parse(source);
        Assert.NotNull(ast);
    }

    #endregion

    #region 无参数有返回值函数测试

    [Fact]
    public void Example4_NoParamsWithReturn()
    {
        var source = @"求 文字 之 法 获取版本{
    得 ""文语 v1.0""。
}

求 整型 之 法 获取幸运数字{
    得 7。
}

文字 版本 是 获取版本（）。
整型 幸运数 是 获取幸运数字（）。

输出（版本）。
输出（幸运数的文字）。";

        var tokens = Tokenize(source);
        Assert.NotEmpty(tokens);

        var tokenValues = new List<string>();
        foreach (var token in tokens)
        {
            if (!string.IsNullOrWhiteSpace(token.Value))
                tokenValues.Add(token.Value);
        }

        Assert.Contains("求", tokenValues);
        Assert.Contains("之", tokenValues);
        Assert.Contains("法", tokenValues);
        Assert.Contains("得", tokenValues);

        var ast = Parse(source);
        Assert.NotNull(ast);
    }

    #endregion

    #region 有参数有返回值函数测试

    [Fact]
    public void Example5_ParamsWithReturn()
    {
        var source = @"整型 甲，整型 乙 求 整型 之 法 求和{
    整型 结果 是 甲 + 乙。
    得 结果。
}

整型 总和 是 求和（10，20）。
输出（""10 + 20 = "" + 总和的文字）。";

        var tokens = Tokenize(source);
        Assert.NotEmpty(tokens);
        var ast = Parse(source);
        Assert.NotNull(ast);
    }

    [Fact]
    public void Example6_MultiParamsFunction()
    {
        var source = @"整型 长，整型 宽 求 整型 之 法 计算面积{
    得 长 * 宽。
}

整型 长，整型 宽，整型 高 求 整型 之 法 计算体积{
    得 长 * 宽 * 高。
}

整型 面积 是 计算面积（5，3）。
整型 体积 是 计算体积（5，3，2）。

输出（""面积："" + 面积的文字）。
输出（""体积："" + 体积的文字）。";

        var tokens = Tokenize(source);
        Assert.NotEmpty(tokens);
        var ast = Parse(source);
        Assert.NotNull(ast);
    }

    #endregion

    #region 标准函数测试

    [Fact]
    public void Example7_OutputFunction()
    {
        var source = @"输出（""你好，世界！""）。

整型 年龄 是 10。
输出（""年龄："" + 年龄）。

实型 价格 是 99.99。
输出（价格的文字）。";

        var tokens = Tokenize(source);
        Assert.NotEmpty(tokens);
        var ast = Parse(source);
        Assert.NotNull(ast);
    }

    [Fact]
    public void Example8_FunctionInExpression()
    {
        var source = @"整型 甲，整型 乙 求 整型 之 法 求和{
    得 甲 + 乙。
}

整型 总计 是 求和（10，20）+ 求和（30，40）。
输出（""结果是："" + 求和（5，10）的文字）。";

        var tokens = Tokenize(source);
        Assert.NotEmpty(tokens);
        var ast = Parse(source);
        Assert.NotNull(ast);
    }

    #endregion

    #region 复杂示例测试

    [Fact]
    public void Example9_FactorialFunction()
    {
        var source = @"整型 数 求 整型 之 法 阶乘{
    若 数 同 0 则{
        得 1。
    }
    若 数 同 1 则{
        得 1。
    }
    得 数 * 阶乘（数 - 1）。
}

整型 结果 是 阶乘（5）。
输出（""5的阶乘是："" + 结果的文字）。";

        var tokens = Tokenize(source);
        Assert.NotEmpty(tokens);
        var ast = Parse(source);
        Assert.NotNull(ast);
    }

    [Fact]
    public void Example10_ProcessingWithMultipleFunctions()
    {
        var source = @"整型 甲，整型 乙 求 整型 之 法 求和{
    得 甲 + 乙。
}

整型 甲，整型 乙 求 整型 之 法 求差{
    得 甲 - 乙。
}

整型 甲，整型 乙 求 整型 之 法 求积{
    得 甲 * 乙。
}

整型 x 是 10。
整型 y 是 3。

输出（""和："" + 求和（x，y）的文字）。
输出（""差："" + 求差（x，y）的文字）。
输出（""积："" + 求积（x，y）的文字）。";

        var tokens = Tokenize(source);
        Assert.NotEmpty(tokens);
        var ast = Parse(source);
        Assert.NotNull(ast);
    }

    [Fact]
    public void Example11_KeywordRecognition()
    {
        var source = @"整型 参数 求 整型 之 法 处理{
    得 参数 * 2。
}

整型 结果 是 处理（5）。";

        var tokens = Tokenize(source);
        Assert.NotEmpty(tokens);

        var tokenValues = new List<string>();
        foreach (var token in tokens)
        {
            if (!string.IsNullOrWhiteSpace(token.Value))
                tokenValues.Add(token.Value);
        }

        // Verify all function keywords are recognized
        Assert.Contains("求", tokenValues);
        Assert.Contains("之", tokenValues);
        Assert.Contains("法", tokenValues);
        Assert.Contains("得", tokenValues);
    }

    #endregion
}
